#include "driverlib.h"

//*****************************************************************************
//
// SCI_setConfig
//
//*****************************************************************************
void SCI_setConfig(uint32_t base, uint32_t lspclkHz, uint32_t baud, uint32_t config)
{
    uint32_t divider;

    //
    // Check the arguments.
    // Is the required baud rate greater than the maximum rate supported?
    //
    ASSERT(SCI_isBaseValid(base));
    ASSERT(baud != 0U);
    ASSERT((baud * 16U) <= lspclkHz);

    SCI_setBaud(base, lspclkHz, baud);

    //
    // Set parity, data length, and number of stop bits.
    //
    HWREG(base + SCI_O_LCR)
        = ((HWREG(base + SCI_O_LCR)
               & ~(SCI_CONFIG_PAR_MASK | SCI_CONFIG_STOP_MASK | SCI_CONFIG_WLEN_MASK))
            | config);
}

//*****************************************************************************
//
// SCI_writeCharArray
//
//*****************************************************************************
void SCI_writeCharArray(uint32_t base, void *array, uint16_t length)
{
    //
    // Check the arguments.
    //
    ASSERT(SCI_isBaseValid(base));

    uint16_t i;
    for (i = 0U; i < length; i++)
    {
        //
        // Wait until space is available in the transmit FIFO.
        //
        while ((HWREG(base + SCI_O_LSR) & SCI_LSR_THRE) == 0)
        { }

        //
        // Send a char.
        //
        HWREG(base + SCI_O_THR) = ((char *)array)[i];
    }
}

//*****************************************************************************
//
// SCI_readCharArray
//
//*****************************************************************************
void SCI_readCharArray(uint32_t base, void *array, uint16_t length)
{
    //
    // Check the arguments.
    //
    ASSERT(SCI_isBaseValid(base));

    uint16_t i;
    for (i = 0U; i < length; i++)
    {
        //
        // Wait until a character is available in the receive buffer.
        //
        while ((HWREG(base + SCI_O_LSR) & SCI_LSR_DR) == 0)
        { }

        //
        // Return the character from the receive buffer.
        //
        ((char *)array)[i] = HWREG(base + SCI_O_RBR);
    }
}

//*****************************************************************************
//
// SCI_setBaud
//
//*****************************************************************************
void SCI_setBaud(uint32_t base, uint32_t lspclkHz, uint32_t baud)
{
    //
    // Compute the baud rate divider {ROUND TO NEAREST INTEGER}
    // bandrate = lspclkHz / 16 / (DLL.(DLF/16*10);
    //
    float val = (float)lspclkHz / 16 / baud;
    float dlf = (val - (int)val) * 16;
    if ((dlf - (int)dlf) >= 0.5)
        dlf = dlf + 1;

    //
    // Set the baud rate.
    //
    HWREG(base + SCI_O_LCR) |= SCI_LCR_DLAB;
    HWREG(base + SCI_O_DLH) = (int)val >> 8;
    HWREG(base + SCI_O_DLL) = (int)val & 0xFF;
    HWREG(base + SCI_O_DLF) = dlf;
    HWREG(base + SCI_O_LCR) &= ~SCI_LCR_DLAB;
}
